package com.ruoyi.zxbh.utils;

import com.arcsoft.face.*;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.enums.ErrorInfo;
import com.arcsoft.face.toolkit.ImageInfo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;


/**
 * @author Administrator
 */
@Component
public class ArcFaceEngineUtil {
    @Value("${arcface.appId}")
    public String appId;
    @Value("${arcface.sdkKey}")
    public String sdkKey;
//    @Value("${arcface.dllPath}")
//    public String dllPath;
    int errorCode;
    private FaceEngine faceEngine;

    String projectPath = System.getProperty("user.dir");

    //初始化引擎
    @PostConstruct
    public void init() {
        try {
            // 1. 加载DLL（直接使用编译后的绝对路径）
            String dllPath = getClass().getClassLoader().getResource("libs/WIN64/libarcsoft_face.dll").getPath();
            dllPath = URLDecoder.decode(dllPath, StandardCharsets.UTF_8.name()); // 处理路径中的空格等特殊字符
            System.out.println("加载DLL路径：" + dllPath);
            System.load(dllPath); // 直接加载DLL

            // 2. 初始化引擎（无参构造函数）
            faceEngine = new FaceEngine();

            // 3. 激活引擎（后续代码不变）
            errorCode = faceEngine.activeOnline(appId, sdkKey);
            if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
                System.out.println("引擎激活失败，错误码：" + errorCode);
                return;
            }

            // 引擎配置和初始化（保持不变）
            EngineConfiguration engineConfiguration = new EngineConfiguration();
            engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
            engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
            engineConfiguration.setDetectFaceMaxNum(10);
            engineConfiguration.setDetectFaceScaleVal(16);

            FunctionConfiguration functionConfiguration = new FunctionConfiguration();
            functionConfiguration.setSupportAge(true);
            functionConfiguration.setSupportFace3dAngle(true);
            functionConfiguration.setSupportFaceDetect(true);
            functionConfiguration.setSupportFaceRecognition(true);
            functionConfiguration.setSupportGender(true);
            functionConfiguration.setSupportLiveness(true);
            functionConfiguration.setSupportIRLiveness(true);
            engineConfiguration.setFunctionConfiguration(functionConfiguration);

            errorCode = faceEngine.init(engineConfiguration);
            if (errorCode != ErrorInfo.MOK.getValue()) {
                System.out.println("初始化引擎失败，错误码：" + errorCode);
            } else {
                System.out.println("虹软人脸识别引擎初始化成功！");
            }
        } catch (Exception e) {
            System.out.println("虹软引擎初始化异常：" + e.getMessage());
            e.printStackTrace();
        }
    }
    /**
     * 加载虹软SDK的DLL文件
     */
    private void loadArcsoftDll() throws Exception {
        // 从classpath中获取DLL文件
        URL dllUrl = getClass().getClassLoader().getResource("libs/WIN64/libarcsoft_face.dll");
        if (dllUrl == null) {
            throw new IOException("未找到libarcsoft_face.dll文件，请检查资源路径！");
        }

        // 创建临时文件
        File tempDir = new File(System.getProperty("java.io.tmpdir"), "arcsoft-dll");
        if (!tempDir.exists()) {
            tempDir.mkdirs();
        }

        // 复制DLL到临时目录
        File tempDll = new File(tempDir, "libarcsoft_face.dll");
        Files.copy(dllUrl.openStream(), tempDll.toPath(), StandardCopyOption.REPLACE_EXISTING);

        // 添加临时目录到系统库路径
        addLibraryPath(tempDir.getAbsolutePath());

        // 加载DLL
        System.loadLibrary("libarcsoft_face");
        System.out.println("成功加载libarcsoft_face.dll，路径：" + tempDll.getAbsolutePath());
    }

    /**
     * 动态添加路径到java.library.path
     */
    private void addLibraryPath(String pathToAdd) throws Exception {
        final java.lang.reflect.Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
        usrPathsField.setAccessible(true);

        // 获取原路径数组
        final String[] paths = (String[]) usrPathsField.get(null);

        // 检查路径是否已存在
        for (String path : paths) {
            if (path.equals(pathToAdd)) {
                return;
            }
        }

        // 添加新路径
        final String[] newPaths = java.util.Arrays.copyOf(paths, paths.length + 1);
        newPaths[newPaths.length - 1] = pathToAdd;
        usrPathsField.set(null, newPaths);
    }

    // 其他方法保持不变...
    // 获取人脸特征、相似度比对、用户信息获取等方法

    //    获取人脸特征
    public FaceFeature getFaceFeature(File file) {


        //人脸检测
        ImageInfo imageInfo = getRGBData(file);
        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
        try {
            errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
        } catch (Exception e) {
            return null;
        }
        System.out.println(faceInfoList);

        //特征提取
        FaceFeature faceFeature = new FaceFeature();
        try {
            errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
        } catch (Exception e) {
            return null;
        }
        return faceFeature;
    }

    //    相似度比对
    public FaceSimilar compareFaceFeature(FaceFeature targetFaceFeature0, FaceFeature sourceFaceFeature0) {
        FaceFeature targetFaceFeature = new FaceFeature();
        targetFaceFeature.setFeatureData(targetFaceFeature0.getFeatureData());
        FaceFeature sourceFaceFeature = new FaceFeature();
        sourceFaceFeature.setFeatureData(sourceFaceFeature0.getFeatureData());

        FaceSimilar faceSimilar = new FaceSimilar();
        faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
        return faceSimilar;
    }

    //用户信息获取
    public HashMap<String, Object> getUserInfo(File file) {
        ImageInfo imageInfo = getRGBData(file);
        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
        errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);

        //设置活体测试
        errorCode = faceEngine.setLivenessParam(0.5f, 0.7f);
        //人脸属性检测
        FunctionConfiguration configuration = new FunctionConfiguration();
        configuration.setSupportAge(true);
        configuration.setSupportFace3dAngle(true);
        configuration.setSupportGender(true);
        configuration.setSupportLiveness(true);
        errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration);
        HashMap<String, Object> map = new HashMap<>();

        //性别检测
        List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>();
        errorCode = faceEngine.getGender(genderInfoList);
        System.out.println("性别：" + genderInfoList.get(0).getGender());
        map.put("gender", genderInfoList.get(0).getGender());
        //年龄检测
        List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>();
        errorCode = faceEngine.getAge(ageInfoList);
        System.out.println("年龄：" + ageInfoList.get(0).getAge());
        map.put("age", ageInfoList.get(0).getAge());
        //3D信息检测
        List<Face3DAngle> face3DAngleList = new ArrayList<Face3DAngle>();
        errorCode = faceEngine.getFace3DAngle(face3DAngleList);
        System.out.println("3D角度：" + face3DAngleList.get(0).getPitch() + "," + face3DAngleList.get(0).getRoll() + "," + face3DAngleList.get(0).getYaw());
        map.put("3DAngle", face3DAngleList.get(0));
        //活体检测
        List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
        errorCode = faceEngine.getLiveness(livenessInfoList);
        System.out.println("活体：" + livenessInfoList.get(0).getLiveness());
        map.put("liveness", livenessInfoList.get(0).getLiveness());


        return map;
    }


}
